package com.feishi.core.util.bitbyte;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.nio.charset.Charset;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Created by caixq on 2/22 022.
 */
public class ByteUtil {

    public static byte getCrc(byte[] data) {
        byte crc = (byte) 0x00;
        for (byte aData : data) {
            crc ^= aData;
        }
        return crc;
    }

    public static String getHexStringSplitBySpace(byte[] bytes){
        StringBuffer sb=new StringBuffer();
        for (byte b : bytes) {
            sb.append(String.format("%02X",(0xFFl)&(b))).append(" ");
        }
        return sb.toString();
    }

    public static String getHexString(byte[] bytes){
        return getHexString(bytes,0,bytes.length);
    }
    public static String getHexString(byte[] bytes, int start, int end){
        StringBuffer sb=new StringBuffer();
        for (int i = start; i < end; i++) {
            sb.append(String.format("%02X",(0xFFl)&(bytes[i])));
        }
        return sb.toString();
    }
//    public static String getHexString(byte[] bytes,int start,int end){
//        StringBuffer sb=new StringBuffer();
//        for (int i = start; i < end; i++) {
//            sb.append(String.format("%02X",Byte.toUnsignedInt(bytes[i])));
//        }
//        return sb.toString();
//    }

    /**
     * 去转义
     */
    public static byte[] removeEscapeCode(byte[] bytes, char escapeCode) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int index = 0;
        for (int i = 0; i < bytes.length; i++) {
            if (bytes[i] == escapeCode) {
                i++;
            }
            bytes[index++] = bytes[i];
        }
        out.write(bytes, 0, index);
        return out.toByteArray();
    }

    /**
     * 追加转义字符
     */
    public static byte[] addEscapeCode(byte[] bytes, char escapeCode, byte[] targets) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int index = 0;
        List list = Arrays.asList(targets);
        byte[] result = new byte[bytes.length * 2];
        for (int i = 0; i < bytes.length; i++) {
            if (list.contains(bytes[i])) {
                result[index++] = (byte) escapeCode;
            }
            result[index++] = bytes[i];
        }
        out.write(result, 0, index);
        return out.toByteArray();
    }

    /**
     * 替换byte数组
     */
    public static byte[] replace(byte[] bytes, byte[] from, byte[] to) {
        if (bytes == null || from == null || from.length == 0 || to == null) {
            return bytes;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int index = 0;
        boolean flag;
        byte[] outBytes = new byte[from.length >= to.length ? bytes.length : ((bytes.length / from.length + 1) * to.length)];

        for (int i = 0; i < bytes.length; i++) {
            flag = true;
            for (int j = 0; j < from.length; j++) {
                if (!(bytes[i + j] == from[j])) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                for (int j = 0; j < to.length; j++) {
                    outBytes[index++] = to[j];
                }
                i += from.length - 1;
            } else {
                outBytes[index++] = bytes[i];
            }
        }
        out.write(outBytes, 0, index);
        return out.toByteArray();
    }

    public static boolean equals(byte[] arr1, byte[] arr2) {
        return Arrays.equals(arr1, arr2);
    }

    public static int indexOf(byte[] a, byte[] a2) {
        if (a == a2)
            return 0;
        if (a == null || a2 == null)
            return -1;

        int length = a.length;
        int length2 = a2.length;
        boolean result;
        for (int i = 0; i <= length - length2; i++) {
            result = true;
            for (int j = 0; j < length2; j++) {
                if (a[i + j] != a2[j]) {
                    result = false;
                }
            }
            if (result) return i;
        }
        return -1;
    }

    public static short toShort(byte[] bytes) {
        short result = 0;
        int index = 0;
        int length = bytes.length;
        while (index < length) {
            result = (short) ((result << 8) | ((bytes[index] & 0xff)));
            index++;
        }
        return result;
    }
    public static int toInt(byte[] bytes) {
        int result = 0;
        int index = 0;
        int length = bytes.length;
        while (index < length) {
            result = (result << 8) | ((bytes[index] & 0xff));
            index++;
        }
        return result;
    }

    public static long toLong(byte[] bytes) {
        long result = 0;
        int index = 0;
        int length = bytes.length;
        while (index < length) {
            result = (result << 8) | (0xFFl)&bytes[index];
            index++;
        }
        return result;
    }

    /**
     * <pre>
     * 将一个16位的short转换为长度为2的8位byte数组.
     * </pre>
     *
     * @param s
     * @return
     */
    public static byte[] shortToByte2(Short s) {
        byte[] arr = new byte[2];
        arr[0] = (byte) (s >> 8);
        arr[1] = (byte) (s & 0xff);
        return arr;
    }

    public static byte[] numberToByte(long number, int size) {
        byte[] result = new byte[size];
        for (int i = size - 1; i >= 0; i--) {
            result[i] = (byte) (number & 0xff);
            number >>= 8;
        }
        return result;
    }

    /**
     * <pre>
     * 长度为2的8位byte数组转换为一个16位short数字.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static short byte2ToShort(byte[] arr) {
        if (arr != null && arr.length != 2) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是2位!");
        }
        return (short) (((short) arr[0] << 8) | ((short) arr[1] & 0xff));
    }

    /**
     * <pre>
     * 将32位int转换为由四个8位byte数字.
     * </pre>
     *
     * @param sum
     * @return
     */
    public static byte[] intToByte4(int sum) {
        byte[] arr = new byte[4];
        arr[0] = (byte) (sum >> 24);
        arr[1] = (byte) (sum >> 16);
        arr[2] = (byte) (sum >> 8);
        arr[3] = (byte) (sum & 0xff);
        return arr;
    }

    /**
     * 将一个long数字转换为8个byte数组组成的数组.
     */
    public static byte[] longToByte8(long sum) {
        byte[] arr = new byte[8];
        arr[0] = (byte) (sum >> 56);
        arr[1] = (byte) (sum >> 48);
        arr[2] = (byte) (sum >> 40);
        arr[3] = (byte) (sum >> 32);
        arr[4] = (byte) (sum >> 24);
        arr[5] = (byte) (sum >> 16);
        arr[6] = (byte) (sum >> 8);
        arr[7] = (byte) (sum & 0xff);
        return arr;
    }


    /**
     * <pre>
     * 将长度为4的8位byte数组转换为32位int.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static int byte4ToInt(byte[] arr) {
        if (arr == null || arr.length != 4) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是4位!");
        }
        return ((arr[0] & 0xff) << 24) | ((arr[1] & 0xff) << 16) | ((arr[2] & 0xff) << 8) | ((arr[3] & 0xff));
    }

    public static long byte8ToLong(byte[] arr) {
        if (arr == null || arr.length != 8) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是8位!");
        }
        return ((long) (arr[0] & 0xff) << 56) | ((long) (arr[1] & 0xff) << 48) | ((long) (arr[2] & 0xff) << 40)
                | ((long) (arr[3] & 0xff) << 32) | ((long) (arr[4] & 0xff) << 24)
                | ((long) (arr[5] & 0xff) << 16) | ((long) (arr[6] & 0xff) << 8) | ((long) (arr[7] & 0xff));
    }

    public static byte[] get(byte[] bytes, int index, int length) {
        byte[] result = new byte[length];
        System.arraycopy(bytes, index, result, 0, length);
        return result;
    }

    public static void copy(byte[] bytes, int position, byte[] result, int start, int length) {
        System.arraycopy(bytes, position, result, start, length);
    }

    public static byte[] fixLength(byte[] bytes, int length) {
        if (bytes.length == length) {
            return bytes;
        }
        byte[] bs = new byte[length];
        int off = bs.length - bytes.length;
        int start = off > 0 ? 0 : -off;
        int targetStart = off > 0 ? off : 0;
        int targetLength = off < 0 ? bs.length : bytes.length;

        System.arraycopy(bytes, start, bs, targetStart, targetLength);
        return bs;
    }

    public static byte[] reverse(byte[] objs) {
        byte t = 0;
        for (int start = 0, end = objs.length - 1; start < end; start++, end--) {
            t = objs[end];
            objs[end] = objs[start];
            objs[start] = t;
        }
        return objs;
    }

    public static byte[] stringToBcd(String str) {
        if (str == null) {
            return null;
        }
        if (str.length() % 2 == 1) {
            str = "0" + str;
        }
        byte[] result = new byte[str.length() / 2];
        for (int i = 0; i < result.length; i++) {
            result[i] = (byte) ((Byte.parseByte(str.charAt(2 * i) + "") << 4) + Byte.parseByte(str.charAt(2 * i + 1) + ""));
        }
        return result;
    }

    public static byte[] concat(byte[]... bf) {
        int length=0;
        for (byte[] bytes : bf) {
            length+=bytes.length;
        }
        byte[] out=new byte[length];
        int index=0;
        for (byte[] bytes : bf) {
            System.arraycopy(bytes,0,out,index,bytes.length);
            index+=bytes.length;
        }
        return out;
    }
    public static interface Filter{
        public boolean execute(byte b);
    }
    public static int findIndex(byte[] bytes,int start, Filter... calls) {
        boolean result;
        int index;
        for (int i = start; i < bytes.length; i++) {
            index=0;
            result=true;
            for (Filter call : calls) {
                if((i+index>=bytes.length)||!call.execute(bytes[i+index])){
                    result=false;
                }
                index++;
            }
            if (result){
                return i;
            }
        }

        return -1;
    }

    /**
     * 高位在前
     */
    public static class BitByte {
        private byte[] bytes;
        private int position = 0;
        private int type= BitByteConfig.MOTOROLA;


        public BitByte(byte[] bytes) {
            this.bytes = bytes;
        }

        public byte[] read(int length) {
            if (!hasLeft() || length <= 0) {
                return null;
            }
            byte[] result = read(position, length);
            position += length;
            return result;
        }

        public int getInt(int length) {
            return toInt(read(length));
        }

        public short getShort(int length) {
            return toShort(read(length));
        }
        public byte getByte() {
            return read(8)[0];
        }

        public long getLong(int length) {
            return toLong(read(length));
        }

        public String getString(int length) {
            return new String(read(length));
        }

        public long getBcdLong(int length) {
            return bcdToLong(read(length));
        }

        public String getBcdString(int length) {
            return bcdToString(read(length));
        }

        public int getInt(int position,int length) {
            return toInt(read(position,length));
        }

        public short getShort(int position,int length) {
            return toShort(read(position,length));
        }
        public byte getByte(int position) {
            return read(position,8)[0];
        }

        public long getLong(int position,int length) {
            return toLong(read(position,length));
        }

        public String getString(int position, int length) {
            return new String(read(position,length));
        }

        public long getBcdLong(int position,int length) {
            return bcdToLong(read(position,length));
        }

        public String getBcdString(int position, int length) {
            return bcdToString(read(position,length));
        }
        public boolean getBoolean(){
            return read(1)[0]!=0;
        }

        public boolean getBoolean(int position){
            return read(position,1)[0]!=0;
        }

        public byte[] read(int position, int length) {
            if (!hasLeft() || length <= 0) {
                return null;
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte b = 0;
            for (int i = 0; i < length; i++) {
                b = (byte) (b | (((bytes[(position+i) / 8] >> (i % 8)) & 1) << (i) % 8));
                if (i % 8 == 7 || i == length-1) {
                    out.write(b);
                    b = 0;
                }
            }
            byte[] result = out.toByteArray();
            reverse(result);
            return result;
        }
        public byte[] readRight(int position, int length) {
            byte[] result=new byte[length/8+(length%8==0?0:1)];
            for (int i = 0; i < length; i++) {
                result[result.length-1-i/8]|=((bytes[(position+length-1-i)/8]&(1<<(
                        ((position+length)/8==position/8)?(position+i)%8:(
                                i<= (position+length-1)%8?i:(i- (position+length-1)%8-1)
                        )%8
                        )))==0?0:1)<<(i%8);
            }
            return result;
        }
        public byte[] readRightIntel(int position, int length) {
            byte[] result=new byte[length/8+(length%8==0?0:1)];
            for (int i = 0; i < length; i++) {
                result[result.length-1-i/8]|=((bytes[position/8-(position%8+i)/8]&(1<<(position+i)%8))==0?0:1)<<((i)%8);


            }
            return result;
        }


        private boolean hasLeft(int position) {
            return bytes.length * 8 > position;
        }

        private boolean hasLeft() {
            return hasLeft(position);
        }

        public void write(int position, int length, Long value) {
            for (int i = 0; i < length; i++) {
                bytes[(position+i) / 8]|=((value&(1l<<i))==0?0:1)<<((position+i)%8);
            }
        }
        public void writeLeft(int position, int length, byte[] value) {
            for (int i = 0; i < length&& i< value.length*8; i++) {
                bytes[(position+i) / 8]|=((value[i/8]&(1<<((i+position)%8)))==0?0:1)<<((position+i)%8);
            }
        }
        /**
         * 本工具以大端模式组织数值，所以数值由后往前复制（丢弃左端高位）
         * */
        public void writeRight(int position, int length, byte[] value) {
            for (int i = 0; i < length&& i< value.length*8; i++) {
                bytes[(position+length-1-i) / 8]|=((value[value.length-1-i/8]&(1<<(i%8)))==0?0:1)<<(
                                ((position+length)/8==position/8)?(position+i)%8:(
                                        i<= (position+length-1)%8?i:(i- (position+length-1)%8-1)
                                        )%8

                );
            }
        }


        public byte[] get() {
            return bytes;
        }

        public void writeRightIntel(int position, int length, byte[] value) {
            for (int i = 0; i < length; i++) {
                bytes[position/8-(position%8+i)/8]|=((value[value.length-1-i/8]&(1<<(i%8)))==0?0:1)<<((position+i)%8);
            }
        }
    }

    /**
     * 低位在前
     */
    public static class DBCByte {
        private byte[] bytes;
        private int position = 0;

        public DBCByte(byte[] bytes) {
            this.bytes = bytes;
        }

        public byte[] read(int length) {
            if (!hasLeft() || length <= 0) {
                return null;
            }
            byte[] result = read(position, length);
            position += length;
            return result;
        }

        public byte[] read(int position, int length) {
            if (!hasLeft(position) || length <= 0) {
                return null;
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte b = 0;
            for (int i = position; i < position + length; i++) {
                b = (byte) (b | (((bytes[i / 8] >> (i % 8)) & 1) << (i - position) % 8));
                if ((i + 1 - position) % 8 == 0 || i == position + length - 1) {
                    out.write(b);
                    b = 0;
                }
            }
            byte[] result = out.toByteArray();
            reverse(result);
            return result;
        }

        private boolean hasLeft(int position) {
            return bytes.length * 8 > position;
        }

        private boolean hasLeft() {
            return hasLeft(position);
        }
    }
    public static class BitByteConfig{
        public String name;
        public int startBit;
        public int size;
        public double factor=1;
        public double offset=0;
        public double initialValue;
        public static final int INTEL=1;
        public static final int MOTOROLA=0;
    }
    public static class BitByteReader{

        public List<BitByteConfig> list;
        public Map<String,BitByteConfig> configMap;
        public ByteUtil.BitByte bitByte;
        public int type=1;

        public BitByteReader(List<BitByteConfig> bitByteConfigs, byte[] bytes) {
            this(bitByteConfigs,bytes, BitByteConfig.MOTOROLA);
        }

        public BitByteReader(List<BitByteConfig> bitByteConfigs, byte[] bytes, int type) {
            this.type=type;
            this.bitByte=new BitByte(bytes);
            this.list=bitByteConfigs;
            this.configMap=new HashMap<>();
            for (BitByteConfig bitByteConfig : bitByteConfigs) {
                configMap.put(bitByteConfig.name,bitByteConfig);
            }

        }

        public  int getInt( String signalName) {
            return ByteUtil.toInt(getBytes(signalName));
        }

        public  long getLong( String signalName) {
            return ByteUtil.toLong(getBytes(signalName));
        }
        public  double getDouble( String signalName) {
            BitByteConfig config=configMap.get(signalName);
            if(config==null){
                System.out.println("非法信号名称");
                return 0;
            }
            return ByteUtil.toLong(getBytes(config))*config.factor+config.offset;
        }
        public String getString(String signalName) {
            return new String(getBytes(signalName),charset);
        }
        public String getString(String signalName, Charset charset) {
            return new String(getBytes(signalName),charset);
        }
        public String getBCDString(String signalName) {
            return ByteUtil.bcdToString(getBytes(signalName));
        }

        public  byte[] getBytes( String signalName) {
            BitByteConfig config=configMap.get(signalName);
            if(config==null){
                System.out.println("非法信号名称");
                return null;
            }
            return getBytes(config);
        }

        public  byte[] getBytes(BitByteConfig config) {
            int start=config.startBit;
            if(type==1){
                return bitByte.readRightIntel(start, config.size);
            }
            return bitByte.readRight(start, config.size);
        }
    }
    public static class BitByteBuild{
        public List<BitByteConfig> list;
        public int type;

        public BitByteBuild(List<BitByteConfig> list, int type) {
            this.list = list;
            this.type = type;
        }

        public BitByteBuild(List<BitByteConfig> list) {
            this.list = list;
        }

        public Map<String,Object> values=new HashMap<>();
        public void setValue(String name, Object value){
            values.put(name,value);
        }
        public byte[] buildContent(){
            int max=0;
            for (BitByteConfig itemConfig : list) {
                if(type== BitByteConfig.INTEL)
                    max=max>(itemConfig.startBit)?max:(itemConfig.startBit);
                else
                    max=max>(itemConfig.startBit+itemConfig.size-1)?max:(itemConfig.startBit+itemConfig.size-1);
            }
            byte[] bs=new byte[max/8+1];
            ByteUtil.BitByte bitByte=new ByteUtil.BitByte(bs);
            for (BitByteConfig config : list) {
                Object value=values.get(config.name);
                byte[] out=getValue(config,value);
                if (type==1){
                    bitByte.writeRightIntel(config.startBit,config.size,out);
                }else {
                    bitByte.writeRight(config.startBit,config.size,out);
                }
            }
            return bitByte.get();
        }


        private byte[] getValue(BitByteConfig config, Object v) {
            if(v==null){
                v=config.initialValue;
            }
            double value=0;
            if (bs.getClass().isInstance(v)){
                return (byte[]) v;
            }else  if (v instanceof String){
                return ((String)v).getBytes(charset);
            }else  if (v instanceof Integer){
                value= (int) v;
            }else if (v instanceof Double){
                value= (double) v;
            }else if (v instanceof Float){
                value= (float) v;
            }else if(v instanceof Long){
                value= (float) v;
            }
            double val=Math.round(((value-config.offset)/config.factor));

            return  ByteUtil.longToByte8((long)val);

        }

    }
    static byte[] bs=new byte[0];
    public static Charset charset=Charset.defaultCharset();

    public static long bcdToLong(byte[] nums) {
        long result = 0;
        for (byte num : nums) {
            result = result * 10 + (num >> 4);
            result = result * 10 + (num & 0x0f);
        }
        return result;
    }

    public static int bcdToInt(byte[] nums) {
        return (int) bcdToLong(nums);
    }

    public static String bcdToString(byte[] nums) {
        StringBuffer result = new StringBuffer();
        for (byte num : nums) {
            result.append(num >> 4).append(num & 0x0f);
        }
        return result.toString();
    }

    public static class ByteReader {

        private byte[] bytes;
        private int readIndex;

        public ByteReader(byte[] bytes) {
            this.bytes = bytes;
        }

        public byte[] get(int length) {
            byte[] bytes = ByteUtil.get(this.bytes, this.readIndex, length);
            this.readIndex += length;
            return bytes;
        }

        public int getInt(int length) {
            return toInt(get(length));
        }

        public short getShort(int length) {
            return toShort(get(length));
        }
        public byte getByte() {
            return get(1)[0];
        }

        public long getLong(int length) {
            return toLong(get(length));
        }

        public String getString(int length) {
            return new String(get(length));
        }

        public long getBcdLong(int length) {
            return bcdToLong(get(length));
        }

        public String getBcdString(int length) {
            return bcdToString(get(length));
        }

        public byte[] getLeft() {
            return get(bytes.length - readIndex);
        }
    }




    private static void printBytes(byte[] bs) {
        for (byte b : bs) {
            System.out.println(Integer.toBinaryString((0xFF)&b));
        }
    }

    private static String code64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=";
    private static String code32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
    private static String code16 = "0123456789ABCDEF";

    public static String encodeToString16(byte[] bytes) throws Exception {
        return encodeToString(bytes, code16);
    }

    public static String encodeToString32(byte[] bytes) throws Exception {
        return encodeToString(bytes, code32);
    }

    public static String encodeToString64(byte[] bytes) throws Exception {
        return encodeToString(bytes, code64);
    }

    public static String encodeToString(byte[] bytes, String code) throws Exception {
        if (code == null) {
            code = code16;
        }
        String result = "";
        int index = 0;
        int length = (int) (Math.log(code.length() + 1) / Math.log(2));
        int currentValue = 0;
        int currentLength = 0;
        while (index <= bytes.length) {
            if (currentLength < length && index < bytes.length) {
                byte b = bytes[index];
                currentValue = (0xFF)&(b);
                index++;
                currentLength += 8;
                continue;
            }
            if (index == bytes.length) {
                if (currentLength == 0) {
                    break;
                }
                if (currentLength - length < 0) {
                    int plus = (int) Math.pow(2, length - currentLength);
                    result += code.charAt(currentValue * plus);
                    break;
                }
            }
            int reduce = (int) Math.pow(2, currentLength - length);
            currentLength = currentLength - length;
            result += code.charAt(currentValue / reduce);
            currentValue = currentValue % reduce;
        }
        return result;
    }

    public static byte[] decode16ToByte(String formatStr) {
        return decodeToByte(formatStr, code16);
    }

    public static byte[] decode32ToByte(String formatStr) {
        return decodeToByte(formatStr, code32);
    }

    public static byte[] decode64ToByte(String formatStr) {
        return decodeToByte(formatStr, code64);
    }

    public static byte[] decodeToByte(String formatStr, String code) {
        List<Byte> byteList = new ArrayList<Byte>();
        int index = 0;
        int length = (int) (Math.log(code.length() + 1) / Math.log(2));
        int plus = (int) Math.pow(2, length);
        int currentValue = 0;
        int currentLength = 0;
        build(formatStr, code, byteList, index, length, plus, currentValue, currentLength);
        byte[] bytes = new byte[byteList.size()];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = byteList.get(i);
        }
        return bytes;

    }

    static void build(String formatStr, String code, List<Byte> byteList, int index, int length, int plus, int currentValue, int currentLength) {
        while (index <= formatStr.length()) {
            if (currentLength < 8 && index < formatStr.length()) {
                currentValue = currentValue * plus + code.indexOf(formatStr.charAt(index));
                currentLength += length;
                index++;
                continue;
            }

            int reduce = (int) Math.pow(2, currentLength - 8);
            currentLength = currentLength - 8;
            byteList.add((byte) (currentValue / reduce));
            currentValue = currentValue % reduce;
            if (index == formatStr.length()) {
                index++;
            }
        }
    }

    public static int floatToInt(float f) {
        return Float.floatToIntBits(f);
    }

    public static long doubleToLong(double d) {
        return Double.doubleToLongBits(d);
    }
    public static short[] bytesToInts(byte[] bytes) {
        /**
         * 默认数据为大端数据
         * */
        return bytesToShorts(bytes,ByteOrder.BIG_ENDIAN);
    }
    public static short[] bytesToShorts(byte[] bytes) {
        /**
         * 默认数据为大端数据
         * */
        return bytesToShorts(bytes,ByteOrder.BIG_ENDIAN);
    }
    public static short[] bytesToShorts(byte[] bytes,ByteOrder order) {

        ByteBuffer byteBuffer =getByteBuffer(bytes,order);
        //将byteBuffer转成小端序并获取shortBuffer
        ShortBuffer buffer = byteBuffer.order(order).asShortBuffer();
        short[] shorts = new short[buffer.remaining()];
        //取出shortBuffer中的short数组
        buffer.get(shorts);
        return shorts;
    }
    public static int[] bytesToInts(byte[] bytes,ByteOrder order) {

        ByteBuffer byteBuffer =getByteBuffer(bytes,order);

        IntBuffer intBuffer = byteBuffer.asIntBuffer();
        int[] ints=new int[intBuffer.remaining()];
        intBuffer.get(ints);
        return ints;
    }

    private static ByteBuffer getByteBuffer(byte[] bytes, ByteOrder order) {
        return ByteBuffer.wrap(bytes).order(order);
    }

    /**
     * 参数 0x11 0x12 0x32 0x66
     * */
    public static byte[] getBytesFromHex(String hexStr) {
        String[] s = hexStr.trim().replaceAll("0[xX]", "").split("\\s");
        byte[] bs=new byte[s.length];
        for (int i = 0; i < bs.length; i++) {
            bs[i]= (byte) Integer.parseInt(s[i],16);
        }
        return bs;
    }


    public static byte[] getBytesFromHexWithoutSpace(String hexStr,int step) {
        step=step<=0?1:step;
        /**
         * 右补齐0
         * */
        int length= (int) Math.ceil(hexStr.length()*1.0/step);
        for (int i = hexStr.length(); i <length*step ; i++) {
            hexStr+=0;
        }
        byte[] bs=new byte[length];
        for (int i = 0; i < length; i++) {
            bs[i]= (byte) Integer.parseInt(hexStr.substring(i*step,i*step+step),16);
        }
        return bs;
    }


    /**
     * 参数 0x11 0x12 0x32 0x66
     * */
    public static byte[] getBytesFromSplitBytes(String hexStr) {
        String[] s = hexStr.trim().split("\\s");
        byte[] bs=new byte[s.length];
        for (int i = 0; i < bs.length; i++) {
            String value = s[i];
//            System.out.println(value);
            if(value.matches("0?[bB]\\d+")){
//                System.out.println(value.replaceAll("0?[bB]",""));
                bs[i]= (byte) Integer.parseInt(value.replaceAll("0?[bB]",""),2);
            }else if(value.matches("0?[xX][a-fA-F\\d]+")){
//                System.out.println(value.replaceAll("0?[xX]",""));
                bs[i]= (byte) Integer.parseInt(value.replaceAll("0?[xX]",""),16);
            }else{
                bs[i]= (byte) Integer.parseInt(value);
            }
        }
        return bs;
    }

    public static void main(String[] args) throws Exception {
//        String aaa = "578%%$%#^347%^&^";
//        System.out.println(new String(decode16ToByte(encodeToString16(aaa.getBytes()))));
//        System.out.println(encodeToString32(aaa.getBytes()));
//        System.out.println(encodeToString64(aaa.getBytes()));
//        byte[] bs =new byte[]{3,4,5,6,3,4,5,6};
//        System.out.println(Arrays.toString(bytesToInts(bs,ByteOrder.LITTLE_ENDIAN)));
        byte[] bs = new byte[]{0,0,0x1,0x23};
        System.out.println(getHexString(bs).replaceAll("^0*",""));

        System.out.println(Arrays.toString(bs));
        System.out.println(Arrays.toString(getBytesFromSplitBytes("12 0x32 0b11 0B101101 0xf1")));

        String s="0x11";
        System.out.println(s.matches("0?[xX]\\d+"));
    }
    public static void readBytes(InputStream inputStream, Consumer callback) throws IOException {
        byte[] bs=new byte[1000];
        int size=0;
        while (true){
            while (inputStream.available()>0&&(size=inputStream.read(bs,0,1000))>0){
                byte[] bytes=new byte[size];
                System.arraycopy(bs,0,bytes,0,size);
                callback.accept(bytes);
            }
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}